<template>
  <div id="threeBox"></div>
</template>

<script setup>
import { onMounted } from 'vue'
// 引入Three.js
import * as THREE from 'three'
// 引入轨道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 定义宽度和高度
const width = innerWidth
const height = innerHeight
// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 3000)
// 设置相机位置
camera.position.set(0, 0, 500)
// 设置相机朝向
camera.lookAt(0, 0, 0)
// 创建渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染器尺寸
renderer.setSize(width, height)
// AxesHelper：辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150)
scene.add(axesHelper)
//创建正方体（参数为长、宽、高）
const cuboid = new THREE.BoxGeometry(50, 50, 50)
//创建球体（参数为球体半径）
const sphere = new THREE.SphereGeometry(25)
//创建圆柱体（参数为底面半径、顶面半径、高）
const cylinder = new THREE.CylinderGeometry(25, 25, 100)
//创建矩形平面（参数为长、宽）
const rectPlane = new THREE.PlaneGeometry(50, 50)
//创建圆形平面（参数为半径）
const circPlane = new THREE.CircleGeometry(25)

//创建一个基础材质
const basicMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000,
})
//创建一个漫反射材质
const lambertMaterial = new THREE.MeshLambertMaterial({
  color: 0xffff00,
})
// 创建一个高光材质
const phongMaterial = new THREE.MeshPhongMaterial({
  color: 0x00ffc3,
  shininess: 20,
})
// 创建一个Standard材质
const standardMaterial = new THREE.MeshStandardMaterial({
  color: 0x00b0f0,
  metalness: 0, //金属度
  roughness: 0.5, //粗糙度
})
// 创建一个Physical材质
const physicalMaterial = new THREE.MeshPhysicalMaterial({
  color: 0x00ff00,
  metalness: 0, //金属度
  roughness: 0.5, //粗糙度
  clearCoat: 0, //清漆层
  clearCoatRoughness: 0, //清漆层粗糙度
  ior: 1.5, //非金属材质折射率
})
// 创建正方体模型，设置位置位于x轴负半轴
const cuboidMesh = new THREE.Mesh(cuboid, basicMaterial)
cuboidMesh.position.set(-140, 0, 0)
// 创建球体模型，设置位置位于x轴负半轴
const sphereMesh = new THREE.Mesh(sphere, phongMaterial)
sphereMesh.position.set(-70, 0, 0)
// 创建圆柱体模型，设置位置位于原点
const cylinderMesh = new THREE.Mesh(cylinder, lambertMaterial)
cylinderMesh.position.set(0, 0, 0)
// 创建矩形平面模型，设置位置位于x轴正半轴
const rectPlaneMesh = new THREE.Mesh(rectPlane, standardMaterial)
rectPlaneMesh.position.set(70, 0, 0)
// 创建圆形平面模型，设置位置位于x轴正半轴
const circPlaneMesh = new THREE.Mesh(circPlane, physicalMaterial)
circPlaneMesh.position.set(140, 0, 0)

// 将模型添加到场景中
scene.add(cuboidMesh)
scene.add(sphereMesh)
scene.add(cylinderMesh)
scene.add(rectPlaneMesh)
scene.add(circPlaneMesh)

// 创建环境光（参数为光照颜色、光照强度）
const ambient = new THREE.AmbientLight(0xffffff, 0.4)
// 将环境光添加到场景中
scene.add(ambient)
// 创建点光源（参数为光照颜色，光照强度，最大照射距离：0为无限远、衰退量）
const pointLight = new THREE.PointLight(0xffffff, 3000, 0, 1)
// 设置点光源位置
pointLight.position.set(0, 150, 100)
// 将点光源添加到场景中
scene.add(pointLight)
// 创建点光源辅助观察对象（参数为点光源、尺寸）
const pointLightHelper = new THREE.PointLightHelper(pointLight, 2)
// 将点光源辅助观察对象添加到场景中
scene.add(pointLightHelper)
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
// 设置光源的位置
directionalLight.position.set(0, -150, -100)
// 平行光指向的对象
directionalLight.target = sphereMesh
scene.add(directionalLight)
// 创建平行光辅助观察对象
const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5, 0xff0000)
// 将平行光辅助观察对象添加到场景中
scene.add(dirLightHelper)
// 创建聚光灯光源
const spotLight = new THREE.SpotLight(0xffffff, 1.0)
// 设置聚光灯光源位置
spotLight.position.set(-140, 100, 0)
// 设置聚光灯光源照射的目标对象
spotLight.target = cylinderMesh
// 设置聚光灯光源发散角度
spotLight.angle = Math.PI / 6
// 将聚光灯光源添加到场景中
scene.add(spotLight) //光源添加到场景中
// 创建聚光灯光源辅助观察对象
const spotLightHelper = new THREE.SpotLightHelper(spotLight, 0xffffff)
// 将聚光灯光源辅助观察对象添加到场景中
scene.add(spotLightHelper)

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 监听轨道控制器的改变，并在改变后重新渲染
controls.addEventListener('change', (e) => {
  renderer.render(scene, camera)
})
// 渲染Canvas画布，将场景和相机作为参数传入
renderer.render(scene, camera)
// 页面挂载完毕后将domElement插入到页面元素内
onMounted(() => {
  document.getElementById('threeBox').appendChild(renderer.domElement)
})
</script>

<style scoped>
#threeBox {
  width: 100%;
  height: 100%;
}
</style>
